package controller;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;

import AI.Path;

import constans.Globals;
import constans.ResourceManager;
import engine.Map;
import engine.MapMatrix;
import entity.Building;
import entity.Bullet;
import entity.Entity;
import entity.Target;
import entity.Unit;

public class ObjectController {

	public static PlayerController player = new PlayerController();

	private static List<Building> building = new ArrayList<Building>();
	private static List<Unit> unit = new ArrayList<Unit>();
	private static List<Bullet> bullet = new ArrayList<Bullet>();
	
	private List<Entity> dead = new ArrayList<Entity>();
	
	private final static Target target = new Target(Globals.MAP_START, Globals.MAP_SIZE_Y/2);
	private final static Vector2f begin = new Vector2f(Globals.MAP_SIZE_X, Globals.MAP_SIZE_Y/2);
	private final static Target pathBegin = new Target(Globals.MAP_SIZE_X, Globals.MAP_SIZE_Y/2);
	
	private static MapMatrix map = new MapMatrix();
	
	private static boolean wasBuild = false;

	public void render(GameContainer container, Graphics g) throws SlickException
	{	
		target.render(container, g);
		for(Building e : building)
			e.render(container, g);
		for(Unit e : unit)
			e.render(container, g);
		for(Bullet b : bullet)
			b.render(container, g);
	}
	public void update(GameContainer container, int delta) throws SlickException
	{
		for(Building e : building)
			e.update(container, delta);
		if(wasBuild)
		{
			for(Unit e : unit)
				e.findPath();
			wasBuild = false;
		}
		for(Unit e : unit)
		{
			e.update(container, delta);
			if(wasBuild)
				e.findPath();
			if(e.isDead())
				dead.add(e);
		}
		for(Bullet b : bullet)
		{
			b.update(container, delta);
			if(b.isDead())
				dead.add(b);
		}
		
		wasBuild = false;
		removeDeads();
	}
	public void dontDrawRanges()
	{
		for(Building b : building)
			b.setRangeDrawing(false);
	}
	public void addBuilding(Building b)
	{
		map.addEntity(b);
		Path path = new Path(new Vector2f(pathBegin.getI(), pathBegin.getJ()), getTarget());
		if(path.isPath())
		{	
			boolean unitsPath = true;
			for(Unit e : unit)
			{
				if(!e.isDead())
					unitsPath = e.isPath();
				if(!unitsPath)
					break;
			}
			if(unitsPath)
			{
				b.setRangeDrawing(false);
				b.build();
				building.add(b);	
				wasBuild = true;
				player.subMoney(b.getPrice());
			}
			else 
				map.releaseField(b);		
		}
		else
			map.releaseField(b);
		
		
	}
	public boolean isFieldEmpty(int i, int j)
	{
		return map.isFieldEmpty(i, j);	
	}
	
	public void addUnit(Unit u)
	{
		unit.add(u);
		map.addEntity(u);
	}
	
	public static MapMatrix getMap()
	{
		return map;
	}
	public static Vector2f getTarget()
	{
		return new Vector2f(target.getI(), target.getJ());
	}
	public static Vector2f getBegin()
	{
		return begin;
	}

	private void removeDeads()
	{
		for(Entity e : dead)
		{
			if(e.getType() == Entity.UNIT)
			{
				map.releaseField(e);
				player.addMoney(unit.get(unit.indexOf(e)).getPrice());
				unit.remove(e);
				
			}
			if(e.getType() == Entity.BULLET)
				bullet.remove(e);
		}
		dead.clear();
	}
	public static void takeDamage(Unit u, int d)
	{
		if(unit.indexOf(u) >= 0 )//exist
			unit.get(unit.indexOf(u)).increaseLife(d);
	}
	public static void addBullet(Bullet b)
	{
		bullet.add(b);
	}
	public Entity isOnEntity(int mx, int my) {
		
		unpickAll();
		for(Building b : building)
			if(b.isOn(mx, my))
				return b;
		for(Unit u : unit)
			if(u.isOn(mx, my))
				return u;		
			return null;
	}
	public static void sellBuilding(Building b)
	{
		building.remove(b);
		map.releaseField(b);
		player.addMoney(b.getPrice()/2);
		wasBuild = true;
	}
	public boolean isAlive(Entity b)
	{
		if(building.contains(b))
			return true;
		if(unit.contains(b))
			return true;
		return false;
	}
	public void unpickAll()
	{
		for(Building b : building)
			b.setPicked(false);
		for(Unit u : unit)
			u.setPicked(false);

	}
}
